package com.bgi.cg.oss4j.provider.minio.service;

import com.bgi.cg.api.AbstractOssService;
import com.bgi.cg.api.entity.OssResponse;
import com.bgi.cg.oss4j.common.factory.BeanFactory;
import com.bgi.cg.oss4j.common.util.OssUtil;
import com.bgi.cg.oss4j.provider._base.OssSupplierType;
import com.bgi.cg.oss4j.provider.minio.config.MinioOssConfig;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;

import java.io.File;
import java.util.concurrent.Executor;
import java.util.function.Function;

/**
 * @Description MINIO私有云
 * @Author Z.cg
 * @Date 2023/9/8
 * @Version 1.0
 **/
@Slf4j
public class MinioOssService extends AbstractOssService {
    private final MinioOssConfig config;
    private MinioClient client;

    public MinioOssService(MinioOssConfig minioOssConfig, Executor pool) {
        super(pool);
        this.config = minioOssConfig;
        client = MinioClient.builder().credentials(minioOssConfig.getAccessKey(), minioOssConfig.getAccessKeySecret()).endpoint(minioOssConfig.getEndPoint()).build();
        try {
            // 关闭HTTPS 检查
            client.ignoreCertCheck();
        } catch (Exception exception) {
            log.error("【{}】OSS接口访问失败(ignoreCertCheck)：{}", OssSupplierType.QINIU.name(), exception.getMessage());
        }
        // 如果不存在存储桶则创建一个
        if (minioOssConfig.isBucketAutoCreate()) {
            try {
                if (!client.bucketExists(BucketExistsArgs.builder().bucket(minioOssConfig.getBucket()).build())) {
                    client.makeBucket(MakeBucketArgs.builder().bucket(minioOssConfig.getBucket()).build());
                }
            } catch (Exception exception) {
                log.error("【{}】OSS创建bucket失败：{}", OssSupplierType.QINIU.name(), exception.getMessage());
            }
        }
    }

    @Override
    public OssResponse upload(File file) {
        return upload(file, config.getBucket());
    }

    @Override
    public OssResponse upload(File file, String bucketName) {
        return upload(file, bucketName, OssUtil::generatePath);
    }

    @Override
    public OssResponse upload(File file, Function<File, String> fileKeyFunction) {
        return upload(file, config.getBucket(), fileKeyFunction);
    }

    @Override
    public OssResponse upload(File file, String bucketName, Function<File, String> fileKeyFunction) {
        valiConfigIsOk();
        // 生成存储的文件名即存储的路径
        String fileName = fileKeyFunction.apply(file);
        /**
         HashMap<String, String> header = Maps.newHashMap();
         header.put("Content-Disposition", "attachment;filename=" + file.getName());
         **/
        OssResponse ossResponse = OssResponse.builder().filePath(fileName).ossType(OssSupplierType.MINIO.name()).code("0").build();
        try {
            UploadObjectArgs args = UploadObjectArgs.builder().bucket(bucketName).contentType(ContentType.APPLICATION_OCTET_STREAM.getMimeType()).object(fileName).filename(file.getAbsolutePath()).build();
            ObjectWriteResponse response = client.uploadObject(args);
        } catch (Exception exception) {
            log.error("【{}】OSS文件上传失败：{}", OssSupplierType.MINIO.name(), exception.getMessage());
            ossResponse.setFail(exception.getMessage());
        }
        return ossResponse;
    }

    @Override
    public OssResponse genPreviewUrl(String fileName) {
        return null;
    }

    /**
     * 私有空间 生成预览地址，用于临时预览，下载
     *
     * @param fileName
     * @param bucketName
     * @return
     */
    @Override
    public OssResponse genPreviewUrl(String fileName, String bucketName) {
        OssResponse ossResponse = OssResponse.builder().code("0").build();
        GetPresignedObjectUrlArgs originArgs = GetPresignedObjectUrlArgs.builder().bucket(bucketName).method(Method.GET).expiry(BeanFactory.getOssConfig().getDownloadUrlExpireMs()).object(fileName).build();
        try {
            String url = client.getPresignedObjectUrl(originArgs);
            ossResponse.setPreviewUrl(url.toString());
        } catch (Exception exception) {
            log.error("【{}】OSS文件下载失败：{}", OssSupplierType.MINIO.name(), exception.getMessage());
            ossResponse.setFail(exception.getMessage());
        }
        return ossResponse;
    }

    @Override
    public OssResponse delete(String fileName) {
        return delete(fileName, config.getBucket());
    }

    @Override
    public OssResponse delete(String fileName, String bucketName) {
        OssResponse ossResponse = OssResponse.builder().code("0").build();
        try {
            RemoveObjectArgs args = RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build();
            client.removeObject(args);
        } catch (Exception exception) {
            log.error("【{}】OSS文件删除失败：{}", OssSupplierType.MINIO.name(), exception.getMessage());
            ossResponse.setFail(exception.getMessage());
        }
        return ossResponse;
    }
    void valiConfigIsOk() {
        if (!config.configIsOk()) {
            throw new RuntimeException("未配置[accessKey,accessKeySecret,bucket,endPoint,region]值");
        }
    }
}
